package tum0r.webengine.models.utils.netcard

import java.net.Inet4Address
import java.net.NetworkInterface

/**
 * 说明: 网卡信息
 *
 * 创建者: tum0r
 *
 * 时间: 2021/8/25 14:11
 *
 * @param[index] 网卡下标
 * @param[mtu] 最大传输单元
 * @param[name] 网卡名
 * @param[displayName] 网卡显示名
 * @param[hardwareAddress] 网卡硬件地址
 * @param[ips] 网卡IP地址集合
 */
data class NetCard(var index: Int, var mtu: Int, var name: String, var displayName: String, var hardwareAddress: ByteArray?, var ips: ArrayList<IP>) {
    /**
     * 网卡硬件地址的十六进制字符串格式
     */
    private var hardwareAddressString: String = ""

    /**
     * 网卡状态
     */
    private var state: Int = 0

    /**
     * 网卡信息
     *
     * @param[index] 网卡下标
     * @param[mtu] 最大传输单元
     * @param[name] 网卡名
     * @param[displayName] 网卡显示名
     * @param[hardwareAddress] 网卡硬件地址
     * @param[isUp] 网卡是否开启
     * @param[isLoopBack] 是否是回环网卡
     * @param[isPointToPoint] 是否是点对点网卡
     * @param[isVirtual] 是否是虚拟网卡
     * @param[ips] 网卡IP地址集合
     */
    constructor(index: Int, mtu: Int, name: String, displayName: String, hardwareAddress: ByteArray?, isUp: Boolean, isLoopBack: Boolean, isPointToPoint: Boolean, isVirtual: Boolean, ips: ArrayList<IP>) : this(index, mtu, name, displayName, hardwareAddress, ips) {
        setState(0, isUp)
        setState(1, isLoopBack)
        setState(2, isPointToPoint)
        setState(3, isVirtual)
    }

    /**
     * 获取十六进制字符串格式的网卡硬件地址
     */
    fun getHardwareAddressString(): String {
        if (hardwareAddressString.isBlank() && hardwareAddress != null && hardwareAddress!!.isNotEmpty()) {
            val result = StringBuilder()
            var hex: String
            for (a in hardwareAddress!!) {
                hex = Integer.toHexString(a.toInt() and 0xff)
                if (hex.length == 1) result.append("0")
                result.append(hex).append(':')
            }
            hardwareAddressString = result.delete(result.length - 1, result.length).toString()
        }
        return hardwareAddressString
    }

    /**
     * 设置网卡状态
     *
     * @param[bit] 状态所在的位
     * @param[flag] 状态
     */
    private fun setState(bit: Int, flag: Boolean) {
        val target = 1 shl bit
        state = if (flag) state or target else state and target.inv()
    }

    /**
     * 获取网卡状态
     * @param[bit] 状态所在的位
     */
    private fun isState(bit: Int): Boolean = (state and (1 shl bit) != 0)

    /**
     * 网卡是否启用
     */
    fun isUp(): Boolean = isState(0)

    /**
     * 是否是回环网卡
     */
    fun isLoopBack(): Boolean = isState(1)

    /**
     * 是否是点对点网卡
     */
    fun isPointToPoint(): Boolean = isState(2)

    /**
     * 是否是虚拟网卡
     */
    fun isVirtual(): Boolean = isState(3)

    /**
     * 获取网卡信息类的伴生对象
     */
    companion object {
        /**
         * 获取网卡集合
         */
        fun getNetCards(): ArrayList<NetCard> {
            val result = ArrayList<NetCard>()
            val network = NetworkInterface.getNetworkInterfaces()
            while (network.hasMoreElements()) {
                val n = network.nextElement()
                val address = n.inetAddresses
                val ips = ArrayList<IP>()
                while (address.hasMoreElements()) {
                    val a = address.nextElement()
                    if (a is Inet4Address && !a.isLoopbackAddress()) ips.add(IP(a.getAddress(), a.getHostAddress(), a.getHostName(), a.getCanonicalHostName()))
                }
                result.add(NetCard(n.index, n.mtu, n.name, n.displayName, n.hardwareAddress, n.isUp, n.isLoopback, n.isPointToPoint, n.isVirtual, ips))
            }
            return result
        }
    }
}